﻿using System;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading;

using Kannon.Core;

namespace Kannon.Server
{
    public class HttpListenerKannonApplicationServer : MarshalByRefObject, IKannonApplicationServer
    {
        private readonly HttpListener httpListener;

        private Type applicationType;

        public HttpListenerKannonApplicationServer()
        {
            httpListener = new HttpListener {
                Prefixes = { "http://*:8081/" },
                AuthenticationSchemes = AuthenticationSchemes.Basic
            };
        }

        public void Start()
        {
            httpListener.Start();

            httpListener.BeginGetContext(Callback, httpListener);

            Console.WriteLine("Listening on " + httpListener.Prefixes.First() + " in AppDomain " + AppDomain.CurrentDomain.FriendlyName);

            Console.WriteLine("Loaded Server assemblies:");

            foreach(var a in AppDomain.CurrentDomain.GetAssemblies())
                Console.WriteLine("\t" + a.FullName);
        }

        private void Callback(IAsyncResult result)
        {
            if(!httpListener.IsListening) return;

            var context = httpListener.EndGetContext(result);
            ThreadPool.QueueUserWorkItem(new HttpListenerWorker(applicationType).HandleRequest, context);

            httpListener.BeginGetContext(Callback, httpListener);
        }

        public void Stop()
        {
            httpListener.Stop();
        }

        public void HostAssembly(string assemblyFileName)
        {
            Console.WriteLine("Hosting " + assemblyFileName);
            var asm = Assembly.LoadFrom(assemblyFileName);

            applicationType  = (from et in asm.GetExportedTypes() where typeof(KannonApplication).IsAssignableFrom(et) select et).FirstOrDefault();
            

            Console.WriteLine("Running " + applicationType.FullName);
        }
    }
}
